# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

def load_data_set(fileName):      
    numFeat = len(open(fileName).readline().split('\t')) - 1 # 只读一行的长度
    dataMat = []
    labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)						# 返回每行的前两个元素的list
        labelMat.append(float(curLine[-1]))			# 返回每行的最后一个元素的list
    return dataMat,labelMat

def standRegres(x_arr, y_arr):
        # 格式化为矩阵
    x_mat = np.mat(x_arr)
    y_mat = np.mat(y_arr).T
    x_tx = x_mat.T * x_mat
    if np.linalg.det(x_tx) == 0:			# 为啥求x.T * x的行列式啊?
        print("This matrix is singular, cannot do inverse")
        return
    ws = x_tx.I * (x_mat.T * y_mat)
    return ws

def lwlr(testPoint,xArr,yArr,k=0.0001):
    xMat = np.mat(xArr) 
    yMat = np.mat(yArr).T
    m = np.shape(xMat)[0]
    weights = np.mat(np.eye((m)))
    for j in range(m):                      #next 2 lines create weights matrix
        diffMat = testPoint - xMat[j,:]     #
        weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2))
    # weights[j,j]的对角矩阵的意义在于 每个对角的元素 都会只给到xMat的每行元素
    xTx = xMat.T * (weights * xMat)
    #  转置矩阵*源矩阵 的行列式!=0 是矩阵可逆的充分必要条件 
    if np.linalg.det(xTx) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    ws = xTx.I * (xMat.T * (weights * yMat))
    # 返回的是给定的参数 经过权重优化后的 预测的y值
    return testPoint * ws, ws

def lwlrTest(testArr,xArr,yArr,k=1.0):
    m = np.shape(testArr)[0]
    yHat = np.zeros(m)
    for i in range(m):
        yHat[i], weights = lwlr(testArr[i],xArr,yArr,k)
    return yHat, weights


x_arr, y_arr = load_data_set('ex0.txt')
ws = standRegres(x_arr, y_arr)
x_mat = np.mat(x_arr)
y_mat = np.mat(y_arr)
y_hat = x_mat * ws
fig = plt.figure()
ax = fig.add_subplot(111)
sss = y_mat.flatten().A[0]
ax.scatter(x_mat[:, 1].flatten().A[0], y_mat.T[:, 0].flatten().A[0])

x_copy = x_mat.copy()
x_copy.sort(0)
y_hat = x_copy * ws
#ax.plot(x_copy[:, 1],y_hat)
## 样本矩阵的每行是一个样本，每列为一个维度，协方差是按维度计算的
#print(np.corrcoef(y_hat.T, y_mat))


str_ind = x_mat[:,1].argsort(0)
x_sort = x_mat[str_ind][:,0,:]
yHat_new, weights = lwlrTest(x_arr, x_arr, y_arr, k=1.0)
sss =yHat_new[str_ind]
ax.plot(x_sort[:, 1],yHat_new[str_ind])
print('#-------------------------',np.corrcoef(y_hat.T, yHat_new))

# 预测鲍鱼年龄

def rssError(yArr, yHatArr):
    return ((yArr -  yHatArr)**2).sum()

abX, abY = load_data_set('abalone.txt')
yHat01 = lwlrTest(abX[0:99],abX[0:99],abY[0:99],0.1)
yHat1 = lwlrTest(abX[0:99],abX[0:99],abY[0:99],1)
yHat10 = lwlrTest(abX[0:99],abX[0:99],abY[0:99],10)

print(rssError(abY[0:99], yHat01.T))
print(rssError(abY[0:99], yHat1.T))
print(rssError(abY[0:99], yHat10.T))



